package com.jk.service.account;

import com.jk.dao.account.*;
import com.jk.entity.account.AccMenu;
import com.jk.entity.account.AccMenuPermission;
import com.jk.entity.account.AccPermission;
import com.jk.util.AccountUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import org.springframework.dao.DataAccessException;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * ACC_MENU service
 * Tue Sep 22 11:02:19 CST 2015 yanghuan
 */
@Service
public class AccMenuService {

    @Autowired
    private AccMenuDao accMenuDao;
    @Autowired
    private AccPermissionDao accPermissionDao;
    @Autowired
    private AccMenuPermissionDao accMenuPermissionDao;

    public int insert(AccMenu accMenu) {
        return accMenuDao.insert(accMenu);
    }

    public int delete(String accMenuId) {
        return accMenuDao.deleteByPrimaryKey(accMenuId);
    }

    public List<AccMenu> selectAllShowMenus() throws DataAccessException {
        List<AccMenu> menuList = accMenuDao.selectAll();
        if (null == menuList) {
            menuList = new ArrayList<AccMenu>();
        }
        return this.getMenus(menuList, "root");
    }

    public List<AccMenu> selectShowMenus(String pid) throws DataAccessException {
        //授权的菜单集合
        List<AccMenu> menuPermittedList = this.menuPermittedList();
        if ("root".equals(pid)) {
            return this.getRootMenus(menuPermittedList);
        } else {
            return this.getMenus(menuPermittedList, pid);
        }
    }

    public List<Map<String, Object>> getPermissions(String menuId) throws DataAccessException {
        List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
        //菜单是否存在
        AccMenu accMenu = accMenuDao.selectByPrimaryKey(menuId);
        if (accMenu != null) {
            //获取所有权限
            List<AccPermission> permissionList = accPermissionDao.selectAll();
            //获取菜单拥有的权限id
            Set<String> permissionIdSet = accMenuPermissionDao.selectPermissionIdSet(menuId);
            if (null == permissionList) {
                permissionList = new ArrayList<AccPermission>();
            }
            if (null == permissionIdSet) {
                permissionIdSet = new HashSet<String>();
            }
            return AccountUtil.getShowPermissions(permissionIdSet, permissionList, "root");
        } else {
            return mapList;
        }
    }

    @Transactional(value = "account", rollbackFor = Exception.class)
    public void grantPermissions(String accMenuId, String[] perIdArray) throws DataAccessException {
        //获取所有权限
        List<AccPermission> permissions = accPermissionDao.selectAll();
        if (null == permissions) {
            permissions = new ArrayList<AccPermission>();
        }
        Set<String> perIdSet = new HashSet<String>();
        for (String id : perIdArray) {
            perIdSet.add(id);
            List<String> childrenPermissionIds = AccountUtil.getChildrenPermissionIds(id, permissions);
            perIdSet.addAll(childrenPermissionIds);
        }
        //删除菜单权限
        AccMenuPermission accMenuPermission = new AccMenuPermission();
        accMenuPermission.setAccMenuId(accMenuId);
        accMenuPermissionDao.delete(accMenuPermission);
        //授权
        for (String perId : perIdSet) {
            AccMenuPermission menuPermission = new AccMenuPermission();
            menuPermission.setAccMenuPermissionId(UUID.randomUUID().toString());
            menuPermission.setAccMenuId(accMenuId);
            menuPermission.setAccPermissionId(perId);
            accMenuPermissionDao.insert(menuPermission);
        }
    }

    public List<AccMenu> menuPermittedList() throws DataAccessException {
        //获取所有菜单
        List<AccMenu> menuList = accMenuDao.selectAll();
        //获取所有权限
        List<AccPermission> permissionList = accPermissionDao.selectAll();
        //授权的菜单集合
        List<AccMenu> menuPermittedList = new ArrayList<AccMenu>();
        Subject subject = SecurityUtils.getSubject();
        for (AccMenu accMenu : menuList) {
            Set<String> permissionIdSet = accMenu.getPermissionIdSet();
            //权限key集合
            List<String> perKeyList = new ArrayList<String>();
            if (permissionIdSet != null && !permissionIdSet.isEmpty()) {
                for (String perId : permissionIdSet) {
                    AccPermission accPermission = this.getPermission(permissionList, perId);
                    if (accPermission != null) {
                        perKeyList.add(accPermission.getAccPermissionKey());
                    }
                }
            }
            //判断权限
            String[] permissions = perKeyList.toArray(new String[]{});
            boolean permittedAll = subject.isPermittedAll(permissions);
            if (permittedAll) {
                menuPermittedList.add(accMenu);
            }
        }
        return menuPermittedList;
    }

    public List<AccMenu> getRootMenus(List<AccMenu> menus) {
        List<AccMenu> rootMenus = new ArrayList<AccMenu>();
        for (AccMenu menu : menus) {
            if ("root".equals(menu.getAccMenuParentId())) {
                rootMenus.add(menu);
            }
        }
        return rootMenus;
    }

    public List<AccMenu> getMenus(List<AccMenu> menuList, String pid) {
        List<AccMenu> list = new ArrayList<AccMenu>();
        for (AccMenu menu : menuList) {
            if (pid.equals(menu.getAccMenuParentId())) {
                menu.setChildren(getMenus(menuList, menu.getAccMenuId()));
                list.add(menu);
            }
        }
        return list;
    }

    public AccPermission getPermission(List<AccPermission> accPermissionList, String id) {
        for (AccPermission accPermission : accPermissionList) {
            if (id.equals(accPermission.getAccPermissionId())) {
                return accPermission;
            }
        }
        return null;
    }
}

